<!DOCTYPE html>
<html>

<head>
    <title> 2048-game </title>
    <meta charset="utf-8" />
    <style media="screen">
        #game {
            display: none;
            position: absolute;
            left: 0px;
            top: 0px;
            right: 0px;
            bottom: 0px;
            background-color: #9DA5C3;
            opacity: 0.5;
            z-index: 1;
        }

        /* .clear:after {
            content: "";
            display: table;
            clear: both;
        } */

        .left {
            float: left;
        }

        .right {
            float: right;
        }

        .scoreShow {
            height: 50px;
            text-align: center;
            line-height: 50px;
        }

        .model {
            text-decoration: none;
            color: white;
            background-color: #bbada0;
            font-size: 36px;
            border-radius: 10px;
        }

        .head {
            width: 480px;
            height: 50px;
            margin: 0 auto;
            font-size: 25px;
        }

        #gridPanel {
            width: 480px;
            height: 480px;
            margin: 0 auto;
            background-color: #bbada0;
            border-radius: 10px;
            position: relative;
            z-index: 1;
        }

        .grid,
        .cell {
            width: 100px;
            height: 100px;
            border-radius: 6px;
        }

        .grid {
            background-color: #ccc0b3;
            float: left;
            margin: 16px 0 0 16px;
        }

        .cell {
            position: absolute;
            font-size: 60px;
            text-align: center;
            line-height: 100px;
            color: #fff;
        }

        .n2 {
            background-color: #eee3da
        }

        .n4 {
            background-color: #ede0c8
        }

        .n8 {
            background-color: #f2b179
        }

        .n16 {
            background-color: #f59563
        }

        .n32 {
            background-color: #f67c5f
        }

        .n64 {
            background-color: #f65e3b
        }

        .n128 {
            background-color: #edcf72
        }

        .n256 {
            background-color: #edcc61
        }

        .n512 {
            background-color: #9c0
        }

        .n1024 {
            background-color: #33b5e5
        }

        .n2048 {
            background-color: #09c
        }

        .n4096 {
            background-color: #a6c
        }

        .n8192 {
            background-color: #93c
        }

        .n2,
        .n4 {
            color: #776e65
        }

        #gameover {
            width: 100%;
            display: none;
            position: fixed;
            left: 50%;
            right: 50%;
            top: 148px;
            width: 220px;
            height: 200px;
            border-radius: 10px;
            background-color: white;
            margin-left: -110px;
            text-align: center;
            z-index: 5;
        }

        #gameover>a {
            display: inline-block;
            width: 170px;
            height: 50px;
            border-radius: 10px;
            text-decoration: none;
            background-color: #9F8D77;
            color: white;
            font-size: 36px;
        }
    </style>
</head>

<body>
    <div id="game">
    </div>
    <div class="head clear">
        <div class="scoreShow left">
            <span>Score:</span>
            <span id="score"></span>
        </div>
        <div class="selction right" onclick="getModel(event)">
            <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow"
                rel="external nofollow" class="model" value="3">3X3</a>
            <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow"
                rel="external nofollow" class="model" value="4">4X4</a>
            <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow"
                rel="external nofollow" class="model" type="button">5X5</a>
            <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow"
                rel="external nofollow" class="model" type="button">6X6</a>
            <!-- <input type="text" id="model"> -->
            <!-- <button type="button" name="button" id="set">设置游戏</button> -->
        </div>
    </div>
    <div id="gridPanel">
    </div>
    <div id="gameover">
        <h1 id="Score"></h1>
        <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow"
            rel="external nofollow" id="again" onclick="obj.gameStart()">Try again</a>
    </div>
    <script type="text/javascript">
        var arr = [];
        function $(id) {
            return document.getElementById(id);
        }
        function C(cls) {
            return document.getElementsByClassName(cls);
        }
        var obj = {
            ROW: 4,
            CELL: 4,
            r: 0,
            c: 0,
            f: 0, //r行 c列 f查找的下一位置
            keyCd: 0,
            score: 0,
            createEle: 0, //是否需要创建元素
            eleFragment: "", //文档片段变量
            //游戏开始
            gameStart: function () {
                obj.init();
                document.onkeydown = function (e) { //自动获得事件对象
                    switch (e.keyCode) { //判断按键号
                        case 37:
                            obj.keyCd = 1;
                            obj.moveLeft();
                            break;
                        case 38:
                            obj.keyCd = 2;
                            obj.moveUp();
                            break;
                        case 39:
                            obj.keyCd = 1;
                            obj.moveRight();
                            break;
                        case 40:
                            obj.keyCd = 2;
                            obj.moveDown();
                            break;
                    }
                    $("score").innerHTML = obj.score; //更新分数
                }
            },
            //初始化
            init: function () {
                obj.eleFragment = document.createDocumentFragment();
                for (r = 0; r < obj.ROW; r++) {
                    arr.push([]);
                    for (c = 0; c < obj.CELL; c++) {
                        arr[r][c] = 0;
                        if (obj.createEle == 1) {
                            obj.create(r, c);
                        }
                    }
                }
                if (obj.createEle == 1) {
                    obj.createEle = 0;
                    $("gridPanel").innerHTML = ""; //清空原有的元素
                    $("gridPanel").appendChild(obj.eleFragment); //添加元素
                }
                obj.score = 0;
                $("score").innerHTML = obj.score;
                $("game").style.display = "none";
                $("gameover").style.display = "none";
                obj.random(); //开始游戏随机生成两个数
                obj.random();
                obj.updateView();
            },
            //创建div元素，添加到gridPanel中
            create: function (r, c) {
                var grid, cell;
                var increment = 14,
                    grWidth, grHeight, grMarginTop, grMarginLeft, ceWidth, ceHight;
                grid = document.createElement("div");
                cell = document.createElement("div");
                grid.id = "g" + r + c;
                grid.className = "grid";
                cell.id = "c" + r + c;
                cell.className = "cell";

                if (obj.ROW == 3) {
                    increment = 24;
                } else if (obj.ROW == 4) {
                    increment = 18;
                }
                grWidth = grHeight = ceWidth = ceHight = 66 + (6 - obj.ROW) * increment; //优化后
                grMarginTop = grMarginLeft = (480 - grWidth * obj.ROW) / (obj.ROW + 1);
                grid.style.width = grWidth + "px";
                grid.style.height = grHeight + "px";
                grid.style.marginTop = grMarginTop + "px";
                grid.style.marginLeft = grMarginLeft + "px";
                cell.style.width = ceWidth + "px";
                cell.style.height = ceHight + "px";
                cell.style.top = grMarginTop + r * (grMarginTop + ceWidth) + "px";
                cell.style.left = grMarginLeft + c * (grMarginLeft + ceHight) + "px";
                cell.style.lineHeight = ceHight + "px";
                cell.style.fontSize = 30 + (6 - obj.ROW) * 10 + "px";
                obj.eleFragment.appendChild(grid);
                obj.eleFragment.appendChild(cell);
            },
            //随机产生一个新的数
            random: function () {
                while (1) {
                    var row = Math.floor(Math.random() * obj.ROW);
                    var cell = Math.floor(Math.random() * obj.CELL);
                    if (arr[row][cell] == 0) { //判断生成的随机数位置为0才随机生成2或4
                        arr[row][cell] = (Math.random() >= 0.7) ? 4 : 2;
                        break;
                    }
                }
                // var row = Math.floor(Math.random() * 4);
                // var cell = Math.floor(Math.random() * 4);
                // if (arr[row][cell] == 0) { //判断生成的随机数位置为0才随机生成2或4
                // arr[row][cell] = (Math.random() > 0.5) ? 4 : 2;
                // return;
                // }
                // obj.random();//递归影响执行效率
            },
            //更新页面
            updateView: function () {
                var win = 0;
                for (r = 0; r < obj.ROW; r++) {
                    for (c = 0; c < obj.CELL; c++) {
                        if (arr[r][c] == 0) { //值为0的不显示
                            $("c" + r + c).innerHTML = ""; //0不显示
                            $("c" + r + c).className = "cell" //清除样式
                        } else {
                            $("c" + r + c).innerHTML = arr[r][c];
                            $("c" + r + c).className = "cell n" + arr[r][c]; //添加不同数字的颜色
                            if (obj.ROW == 3 && arr[r][c] == 1024) {
                                win = 1;
                            } else if (obj.ROW == 4 && arr[r][c] == 8192) {
                                win = 1;
                            } else if (obj.ROW == 5 && arr[r][c] == 4096) {
                                win = 1;
                            } else if (obj.ROW == 6 && arr[r][c] == 8192) {
                                win = 1;
                            }
                        }
                    }
                }
                if (win == 1) { //通关
                    $("game").style.display = "block";
                    $("gameover").style.display = "block";
                    $("Score").innerHTML = "You win!<br>Score:" + obj.score;
                }
                if (obj.isGameOver()) { //游戏失败
                    $("game").style.display = "block";
                    $("gameover").style.display = "block";
                    $("Score").innerHTML = "GAME OVER!<br>Score:" + obj.score;
                    console.log("gameover");
                }
            },
            //游戏失败
            isGameOver: function () {
                for (r = 0; r < obj.ROW; r++) {
                    for (c = 0; c < obj.CELL; c++) {
                        if (arr[r][c] == 0) { //有0还不是gameover
                            return false;
                        } else if (c != obj.CELL - 1 && arr[r][c] == arr[r][c + 1]) { //左往右 前一个和下一个不相等
                            return false;
                        } else if (r != obj.ROW - 1 && arr[r][c] == arr[r + 1][c]) { //上往下 上一个和下一个不相等
                            return false;
                        }
                    }
                }
                return true;
            },
            //查找下一个不为0的数值的位置
            find: function (r, c, start, condition, direction) {
                if (obj.keyCd == 2) { //上下按键
                    if (direction == 1) { //向上按键 f++
                        for (var f = start; f < condition; f += direction) {
                            if (arr[f][c] != 0) {
                                return f;
                            }
                        }
                    } else { //向下按键 f--
                        for (var f = start; f >= condition; f += direction) {
                            if (arr[f][c] != 0) {
                                return f;
                            }
                        }
                    }
                } else { //左右按键
                    if (direction == 1) { //左按键 f++
                        for (var f = start; f < condition; f += direction) {
                            if (arr[r][f] != 0) {
                                return f;
                            }
                        }
                    } else { //右按键 f--
                        for (var f = start; f >= condition; f += direction) {
                            if (arr[r][f] != 0) {
                                return f;
                            }
                        }
                    }
                }
                return null; //循环结束仍然没有找到！=0的数值，返回null
            },
            //左按键的处理
            dealToLeft: function (r) {
                var next;
                for (c = 0; c < obj.ROW; c++) {
                    next = obj.find(r, c, c + 1, obj.CELL, 1); //找出第一个不为0的位置
                    if (next == null) break; //没有找到就返回
                    //如果当前位置为0
                    if (arr[r][c] == 0) {
                        arr[r][c] = arr[r][next]; //把找到的不为0的数值替换为当前位置的值
                        arr[r][next] = 0; //找到的位置清0
                        c--; //再次循环多一次，查看后面否有值与替换后的值相同，
                    } else if (arr[r][c] == arr[r][next]) { //如果当前位置与找到的位置数值相等，则相加
                        arr[r][c] *= 2;
                        arr[r][next] = 0;
                        obj.score += arr[r][c];
                    }
                }
            },
            move: function (itertor) {
                var before, //没处理前
                    after; //after处理后
                before = arr.toString();
                itertor(); //执行for函数
                after = arr.toString();
                if (before != after) { //前后对比，如果不同就update
                    obj.random();
                    obj.updateView();
                }
            },
            moveLeft: function () {
                obj.move(function () {
                    for (r = 0; r < obj.ROW; r++) {
                        obj.dealToLeft(r);
                    }
                })
                // if 当前位置 不为零
                // 从当前位置，下一个成员开始，遍历，
                // 如果找到，与当前位置相等的数，
                // 两者相加，并把不为零的成员，设置为零
                // 如果 当前位置是 零
                // 从当前位置下一个成员开始遍历
                // 如果找到 第一个不为零的成员
                // 当前位置数值设置为这个不为零的成员的值 ，并且把那个不为零的成员设置为 0
            },
            //右按键处理
            dealToRight: function (r) {
                var next;
                for (c = obj.CELL - 1; c >= 0; c--) {
                    next = obj.find(r, c, c - 1, 0, -1); //找出第一个不为0的位置
                    if (next == null) break; //没有找到就返回
                    //如果当前位置为0
                    if (arr[r][c] == 0) {
                        arr[r][c] = arr[r][next]; //把找到的不为0的数值替换为当前位置的值
                        arr[r][next] = 0; //找到的位置清0
                        c++; //再次循环多一次，查看后面否有值与替换后的值相同，
                    } else if (arr[r][c] == arr[r][next]) { //如果当前位置与找到的位置数值相等，则相加
                        arr[r][c] *= 2;
                        arr[r][next] = 0;
                        obj.score += arr[r][c];
                    }
                }
            },
            moveRight: function () {
                obj.move(function () {
                    for (r = 0; r < obj.ROW; r++) {
                        obj.dealToRight(r);
                    }
                })
            },
            //上按键处理
            dealToUp: function (c) {
                var next;
                for (r = 0; r < obj.ROW; r++) {
                    next = obj.find(r, c, r + 1, obj.ROW, 1); //找出第一个不为0的位置
                    if (next == null) break;
                    //如果当前位置为0
                    if (arr[r][c] == 0) {
                        arr[r][c] = arr[next][c]; //把找到的不为0的数值替换为当前位置的值
                        arr[next][c] = 0; //找到的位置清0
                        r--; //再次循环多一次，查看后面否有值与替换后的值相同
                    } else if (arr[r][c] == arr[next][c]) { //如果当前位置与找到的位置数值相等，则相加
                        arr[r][c] *= 2;
                        arr[next][c] = 0;
                        obj.score += arr[r][c];
                    }
                }
            },
            moveUp: function () {
                obj.move(function () {
                    for (c = 0; c < obj.CELL; c++) {
                        obj.dealToUp(c);
                    }
                })
            },
            //下按键处理
            dealToDown: function (c) {
                var next;
                for (r = obj.ROW - 1; r >= 0; r--) {
                    next = obj.find(r, c, r - 1, 0, -1); //找出第一个不为0的位置
                    if (next == null) {
                        break;
                    }
                    //如果当前位置为0
                    if (arr[r][c] == 0) {
                        arr[r][c] = arr[next][c]; //把找到的不为0的数值替换为当前位置的值
                        arr[next][c] = 0; //找到的位置清0
                        r++; //再次循环多一次，查看后面否有值与替换后的值相同
                    } else if (arr[r][c] == arr[next][c]) { //如果当前位置与找到的位置数值相等，则相加
                        arr[r][c] *= 2;
                        arr[next][c] = 0;
                        obj.score += arr[r][c];
                    }
                }
            },
            moveDown: function () {
                obj.move(function () {
                    for (c = 0; c < obj.CELL; c++) {
                        obj.dealToDown(c);
                    }
                })
            }
        }
        window.onload = function () {
            obj.createEle = 1;
            obj.gameStart();
        }
        //切换模式
        function getModel(e) { //事件冒泡获取a元素
            var a = e.target,
                modelValue = 4;
            if (a.nodeName == "A") {
                if (a.innerHTML == "3X3") {
                    modelValue = 3;
                } else if (a.innerHTML == "4X4") {
                    modelValue = 4;
                } else if (a.innerHTML == "5X5") {
                    modelValue = 5;
                } else if (a.innerHTML == "6X6") {
                    modelValue = 6;
                }
                obj.ROW = obj.CELL = modelValue;
                obj.createEle = 1; //需要创建格子div元素的标志
                obj.gameStart();
            }
        }
 // var modelValue = parseInt($("model").value);
 // if (isNaN(modelValue)) {
 // modelValue = 4; //默认是4*4
 // }
 // if (modelValue <= 2 || modelValue > 6) return; //2格或者大于6格无效
 // obj.ROW = modelValue;
 // obj.CELL = modelValue;
 // obj.createEle = 1;
 // obj.gameStart();
 // console.log(modelValue);
 // }
    </script>
</body>

</html>